package com.brotherly.framework.transaction;

import java.util.HashMap;
import java.util.Map;

import com.brotherly.framework.service.IService;
import com.brotherly.util.Factory;
import com.brotherly.util.ReusablePool;

public class TransactionService implements Factory<Transaction>, IService
{
    public static final String description = "com.brotherly.framework.transaction.TRANSACTION";

    protected Map<String, DriverFactory> driverFactories;
    protected Map<String, PacemakerFactory> pacemakerFactories;

    protected ReusablePool<TransactionTask> taskPools;
    protected ReusablePool<Transaction> tranPools;
    protected Map<String, Transaction> trans;

    public TransactionService()
    {
        tranPools = new ReusablePool<Transaction>(100, this);
        taskPools = new ReusablePool<TransactionTask>(100, new TransactionTask());

        trans = new HashMap<String, Transaction>();
        pacemakerFactories = new HashMap<String, PacemakerFactory>();
        driverFactories = new HashMap<String, DriverFactory>();
    }

    public void activeTransaction(String id)
    {
        Transaction tran = (Transaction) openTransaction(id);

        if (!tran.isActive())
        {
            TransactionTask task = taskPools.alloc();

            tran.putTask(task);

            PacemakerFactory pacemakerFactory = pacemakerFactories.get(tran.getPacemakerType());
            DriverFactory driverFactory = driverFactories.get(tran.getDriverType());

            task.active(tran, pacemakerFactory, driverFactory);

        }
    }

    public void attachParty(String id, Party party)
    {
        Transaction tran = (Transaction) openTransaction(id);

        tran.putParty(party);
    }

    public synchronized Transaction createOrOpenTransaction(String id)
    {
        Transaction tran = (Transaction) openTransaction(id);
        if (tran != null)
            return tran;

        tran = tranPools.alloc();
        tran.clear();
        tran.putId(id);

        trans.put(id, tran);

        return tran;
    }

    public synchronized void destoryTransaction(String id)
    {
        Transaction tran = (Transaction) openTransaction(id);

        if (tran.isActive())
            inactiveTransaction(id);

        trans.remove(id);
        tranPools.free(tran);
    }

    public void inactiveTransaction(String id)
    {
        Transaction tran = (Transaction) openTransaction(id);

        if (tran.isActive())
        {
            TransactionTask task = tran.getTask();

            task.inactive();
            tran.putTask(null);

            taskPools.free(task);
        }
    }

    @Override
    public void init()
    {

    }

    @Override
    public void init(Transaction element)
    {

    }

    @Override
    public Transaction newInstance()
    {
        return new Transaction();
    }

    public synchronized Transaction openTransaction(String id)
    {
        Transaction tran = trans.get(id);
        return tran;
    }

    public synchronized void registerDriverFactory(String type, DriverFactory factory)
    {
        driverFactories.put(type, factory);
    }

    public synchronized void registerPacemakerFactory(String type, PacemakerFactory factory)
    {
        pacemakerFactories.put(type, factory);
    }

    @Override
    public void uninit(Transaction element)
    {

    }

    public synchronized void unregisterDriverFactory(String type)
    {
        driverFactories.remove(type);
    }

    public synchronized void unregisterPacemakerFactory(String type)
    {
        pacemakerFactories.remove(type);
    }
}
